-- Winter Anathema (c) v.v.balashoff
local Color = require('libs/colorlibrary/colorlibrary')
local Domain = require('leviathan/ECS/Domain')
local DomainSwitcherComponent = require('leviathan/ECS/Core/Components/DomainSwitcherComponent')
local DomainSwitcherSystem = require('leviathan/ECS/Core/Systems/DomainSwitcherSystem')
local Entity = require('leviathan/ECS/Entity')
local FadeComponent = require('leviathan/ECS/UI/Components/FadeComponent')
local i18n = require('libs/i18n')
local Log = require('leviathan/Log')
local MouseClickComponent = require('leviathan/ECS/UI/Components/MouseClickComponent')
local MouseHoverComponent = require('leviathan/ECS/UI/Components/MouseHoverComponent')
local TextComponent = require('leviathan/ECS/UI/Components/TextComponent')
local TextureComponent = require('leviathan/ECS/UI/Components/TextureComponent')
local TimerComponent = require('leviathan/ECS/UI/Components/TimerComponent')
local UIFadeSystem = require('leviathan/ECS/UI/Systems/FadeSystem')
local UIInputSystem = require('leviathan/ECS/UI/Systems/InputSystem')
local UIRenderSystem = require('leviathan/ECS/UI/Systems/RenderSystem')
local UITimerSystem = require('leviathan/ECS/UI/Systems/TimerSystem')
local UITweenSystem = require('leviathan/ECS/UI/Systems/TweenSystem')

local DomainSplashScreen = Domain:derive('DomainSplashScreen')

local screensPath = 'src/Domains/Screens'

function DomainSplashScreen:new(world, name, location)
    -- call parent constructor
    DomainSplashScreen.super.new(self, world, name, location)
    -- screen dimensions
    local screenW, screenH = love.window.getMode()
    -- get managers
    local ImagesManager = world:getManager('ImagesManager')
    local FontsManager = world:getManager('FontsManager')
    -- read data
    local path = screensPath..'/'..name
    local scr = require(path)
    local imgName = scr.image
    self.music = scr.music
    local text = i18n.translate(scr.text)
    local fin = scr.fadein
    local fout = scr.fadeout
    local duration = scr.duration
    local follow = scr.follow
    self.skip = scr.skip
    local texture = ImagesManager:getImageTexture(imgName)

    -- background
    local bg = Entity(self, 'SplashScreenBackground', 0, 0, screenW, screenH)
    local bgTextureComp = TextureComponent(texture.texture, 0, 0, screenW, screenH, 'center', 'center', true)
    bg:addComponent(bgTextureComp)

    -- fader in (from black screen to image)
    if fin then
        self.buffer.alpha = 0 -- default unvisible
        local faderIn = Entity(self, 'FaderIn', 0, 0, screenW, screenH)
        local finComp = FadeComponent('FadeInComponent', self.buffer, 1, 'inSine', fin)
        faderIn:addComponent(finComp)
    end

    -- fader out (from image to black screen)
    -- default alpha is 0, totally unvisible
    if fout then
        self.buffer.alpha = 1 -- default visible
        local faderOut = Entity(self, 'FaderOut', 0, 0, screenW, screenH, 0)
        local foutComp = FadeComponent('FadeOutComponent', self.buffer, 0, 'outSine', fout)
        faderOut:addComponent(foutComp)
        -- fade out disable
        foutComp.enabled = false
        -- entity: cronFadeOut
        local cronFadeOut = Entity(self, 'CronFadeOut')
        local t1 = TimerComponent(duration - fout, foutComp, 'enabled', true)
        cronFadeOut:addComponent(t1)
    end

    -- subtitle
    -- calculate subtitle width and height limits
    local sw, sh
    local fontSize = math.floor(screenH * 0.04)
    local font = FontsManager:getFont('TypeWriter', fontSize)
    sw = screenW * 0.80 --  subtitle must occupy 80% of screen width
    sw, sh = FontsManager:getTextSize(font, text, sw)
    local x = math.floor((screenW - sw) / 2)
    local y = math.floor(screenH - sh - fontSize * 0.7)
    -- entity: subtitle
    local subtitle = Entity(self, 'SplashScreenSubtitle', x, y, sw, sh)
    local subtitleTextComp = TextComponent('SubtitleText', 0, 0, sw, sh, text, font, Color.white, 'center', Color.black)
    subtitle:addComponent(subtitleTextComp)

    -- entity: mouse clicker
    local clicker = Entity(self, 'Clicker', 0, 0, screenW, screenH)
    local mouseHoverComponent = MouseHoverComponent()
    mouseHoverComponent.hovered = true -- to get all mouse clicks
    clicker:addComponent(mouseHoverComponent)
    local mouseClickComponent = MouseClickComponent(self.buttonClick, nil, 'ButtonAsyncPressedComponent')
    clicker:addComponent(mouseClickComponent)

    -- entity: cronSwitcher
    local cronSwitcher = Entity(self, 'DomainSwitcher')
    local ds = DomainSwitcherComponent('DomainSwitcherComponent', self, follow)
    ds.enabled = false
    cronSwitcher:addComponent(ds)
    local t2 = TimerComponent(duration, ds, 'enabled', true)
    cronSwitcher:addComponent(t2)

    -- systems
    local fade = UIFadeSystem(self)
    local render = UIRenderSystem(self)
    local input = UIInputSystem(self)
    local switcher = DomainSwitcherSystem(self)
    local timer = UITimerSystem(self)
    local tween = UITweenSystem(self)
    DomainSplashScreen:addSystem(self, fade)
    DomainSplashScreen:addSystem(self, render)
    DomainSplashScreen:addSystem(self, input)
    DomainSplashScreen:addSystem(self, switcher)
    DomainSplashScreen:addSystem(self, timer)
    DomainSplashScreen:addSystem(self, tween)
end

function DomainSplashScreen:onEnter()
    if self.music then
        local audio = world:getDomain('Audio')
        audio:playMusic(self.music)
    end
end

function DomainSplashScreen:onExit(to)
    if to == 'MainMenu' then
        local audio = world:getDomain('Audio')
        audio:stopMusic()
        world:deleteDomain(self)
    end
end

function DomainSplashScreen:buttonClick(button)
    Log:debug('[SplashScreen] ['..self.name..'] => ['..self.skip..']')
    world:switchDomain(self, self.skip)
end

return DomainSplashScreen
